"""
认证相关Pydantic模式
"""
from datetime import datetime
from typing import Optional, List
from pydantic import BaseModel, Field, EmailStr, validator

from .base import BaseSchema, TimestampSchema


class UserBase(BaseModel):
    """用户基础模式"""
    username: str = Field(..., min_length=3, max_length=50, description="用户名")
    email: EmailStr = Field(..., description="邮箱")
    full_name: Optional[str] = Field(None, max_length=100, description="全名")
    phone: Optional[str] = Field(None, max_length=20, description="电话")
    department: Optional[str] = Field(None, max_length=100, description="部门")
    position: Optional[str] = Field(None, max_length=100, description="职位")
    is_active: bool = Field(default=True, description="是否激活")


class UserCreate(UserBase):
    """创建用户模式"""
    password: str = Field(..., min_length=8, max_length=128, description="密码")
    
    @validator('password')
    def validate_password(cls, v):
        """验证密码强度"""
        if len(v) < 8:
            raise ValueError('密码长度至少8位')
        
        has_upper = any(c.isupper() for c in v)
        has_lower = any(c.islower() for c in v)
        has_digit = any(c.isdigit() for c in v)
        has_special = any(c in "!@#$%^&*()_+-=[]{}|;:,.<>?" for c in v)
        
        strength_count = sum([has_upper, has_lower, has_digit, has_special])
        if strength_count < 3:
            raise ValueError('密码必须包含大写字母、小写字母、数字、特殊字符中的至少3种')
        
        return v


class UserUpdate(BaseModel):
    """更新用户模式"""
    email: Optional[EmailStr] = Field(None, description="邮箱")
    full_name: Optional[str] = Field(None, max_length=100, description="全名")
    phone: Optional[str] = Field(None, max_length=20, description="电话")
    department: Optional[str] = Field(None, max_length=100, description="部门")
    position: Optional[str] = Field(None, max_length=100, description="职位")
    is_active: Optional[bool] = Field(None, description="是否激活")


class UserResponse(UserBase, TimestampSchema):
    """用户响应模式"""
    id: int = Field(..., description="用户ID")
    is_superuser: bool = Field(..., description="是否超级用户")
    is_staff: bool = Field(..., description="是否员工")
    last_login: Optional[datetime] = Field(None, description="最后登录时间")


class UserLogin(BaseModel):
    """用户登录模式"""
    username: str = Field(..., description="用户名")
    password: str = Field(..., description="密码")


class UserChangePassword(BaseModel):
    """用户修改密码模式"""
    old_password: str = Field(..., description="旧密码")
    new_password: str = Field(..., min_length=8, max_length=128, description="新密码")
    
    @validator('new_password')
    def validate_new_password(cls, v):
        """验证新密码强度"""
        if len(v) < 8:
            raise ValueError('密码长度至少8位')
        
        has_upper = any(c.isupper() for c in v)
        has_lower = any(c.islower() for c in v)
        has_digit = any(c.isdigit() for c in v)
        has_special = any(c in "!@#$%^&*()_+-=[]{}|;:,.<>?" for c in v)
        
        strength_count = sum([has_upper, has_lower, has_digit, has_special])
        if strength_count < 3:
            raise ValueError('密码必须包含大写字母、小写字母、数字、特殊字符中的至少3种')
        
        return v


class Token(BaseModel):
    """令牌模式"""
    access_token: str = Field(..., description="访问令牌")
    token_type: str = Field(default="bearer", description="令牌类型")
    expires_in: int = Field(..., description="过期时间(秒)")


class TokenData(BaseModel):
    """令牌数据模式"""
    user_id: Optional[int] = Field(None, description="用户ID")
    username: Optional[str] = Field(None, description="用户名")


class RoleBase(BaseModel):
    """角色基础模式"""
    name: str = Field(..., max_length=50, description="角色名称")
    description: Optional[str] = Field(None, description="角色描述")


class RoleCreate(RoleBase):
    """创建角色模式"""
    permission_ids: Optional[List[int]] = Field(default=[], description="权限ID列表")


class RoleUpdate(BaseModel):
    """更新角色模式"""
    name: Optional[str] = Field(None, max_length=50, description="角色名称")
    description: Optional[str] = Field(None, description="角色描述")
    permission_ids: Optional[List[int]] = Field(None, description="权限ID列表")


class RoleResponse(RoleBase, TimestampSchema):
    """角色响应模式"""
    id: int = Field(..., description="角色ID")


class PermissionBase(BaseModel):
    """权限基础模式"""
    name: str = Field(..., max_length=50, description="权限名称")
    codename: str = Field(..., max_length=100, description="权限代码")
    description: Optional[str] = Field(None, description="权限描述")
    module: str = Field(..., max_length=50, description="所属模块")


class PermissionCreate(PermissionBase):
    """创建权限模式"""
    pass


class PermissionUpdate(BaseModel):
    """更新权限模式"""
    name: Optional[str] = Field(None, max_length=50, description="权限名称")
    description: Optional[str] = Field(None, description="权限描述")


class PermissionResponse(PermissionBase, TimestampSchema):
    """权限响应模式"""
    id: int = Field(..., description="权限ID")


class UserSessionResponse(TimestampSchema):
    """用户会话响应模式"""
    id: int = Field(..., description="会话ID")
    user_id: int = Field(..., description="用户ID")
    ip_address: Optional[str] = Field(None, description="IP地址")
    user_agent: Optional[str] = Field(None, description="用户代理")
    expires_at: datetime = Field(..., description="过期时间")
    is_valid: bool = Field(..., description="是否有效")


class LoginResponse(BaseModel):
    """登录响应模式"""
    user: UserResponse = Field(..., description="用户信息")
    token: Token = Field(..., description="访问令牌")
    session: UserSessionResponse = Field(..., description="会话信息")


class UserListResponse(BaseModel):
    """用户列表响应模式"""
    items: List[UserResponse] = Field(..., description="用户列表")
    total: int = Field(..., description="总数量")
    page: int = Field(..., description="当前页码")
    size: int = Field(..., description="每页数量")
    pages: int = Field(..., description="总页数")


class SecurityAuditLog(BaseModel):
    """安全审计日志模式"""
    user_id: Optional[int] = Field(None, description="用户ID")
    action: str = Field(..., description="操作")
    resource: Optional[str] = Field(None, description="资源")
    ip_address: Optional[str] = Field(None, description="IP地址")
    user_agent: Optional[str] = Field(None, description="用户代理")
    success: bool = Field(..., description="是否成功")
    details: Optional[dict] = Field(None, description="详细信息")
    timestamp: datetime = Field(default_factory=datetime.now, description="时间戳")


class SecuritySettings(BaseModel):
    """安全设置模式"""
    password_min_length: int = Field(default=8, ge=6, le=32, description="密码最小长度")
    password_require_uppercase: bool = Field(default=True, description="密码需要大写字母")
    password_require_lowercase: bool = Field(default=True, description="密码需要小写字母")
    password_require_digits: bool = Field(default=True, description="密码需要数字")
    password_require_special: bool = Field(default=True, description="密码需要特殊字符")
    session_timeout_minutes: int = Field(default=30, ge=5, le=1440, description="会话超时时间(分钟)")
    max_login_attempts: int = Field(default=5, ge=3, le=10, description="最大登录尝试次数")
    lockout_duration_minutes: int = Field(default=15, ge=5, le=60, description="锁定持续时间(分钟)")
    enable_two_factor: bool = Field(default=False, description="启用双因素认证")
    allowed_ip_ranges: Optional[List[str]] = Field(default=[], description="允许的IP范围")


class TwoFactorSetup(BaseModel):
    """双因素认证设置模式"""
    secret_key: str = Field(..., description="密钥")
    qr_code_url: str = Field(..., description="二维码URL")
    backup_codes: List[str] = Field(..., description="备用代码")


class TwoFactorVerify(BaseModel):
    """双因素认证验证模式"""
    code: str = Field(..., min_length=6, max_length=6, description="验证码")


class PasswordResetRequest(BaseModel):
    """密码重置请求模式"""
    email: EmailStr = Field(..., description="邮箱")


class PasswordReset(BaseModel):
    """密码重置模式"""
    token: str = Field(..., description="重置令牌")
    new_password: str = Field(..., min_length=8, max_length=128, description="新密码")
    
    @validator('new_password')
    def validate_new_password(cls, v):
        """验证新密码强度"""
        if len(v) < 8:
            raise ValueError('密码长度至少8位')
        
        has_upper = any(c.isupper() for c in v)
        has_lower = any(c.islower() for c in v)
        has_digit = any(c.isdigit() for c in v)
        has_special = any(c in "!@#$%^&*()_+-=[]{}|;:,.<>?" for c in v)
        
        strength_count = sum([has_upper, has_lower, has_digit, has_special])
        if strength_count < 3:
            raise ValueError('密码必须包含大写字母、小写字母、数字、特殊字符中的至少3种')
        
        return v
